import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, Renderer2, Inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormlyFormOptions } from '@ngx-formly/core';
import { FormControl, FormGroup } from '@angular/forms';
import { ApiService } from '@core/services/http/api.service';
import {
  exists, getJson, getO, getText, getValueUsingField, missing, missingOrEmpty,
  type, deepClone, missingOrEmptyObject, replaceAll,
} from '../../utils/utils';
import { SearchService } from '@core/services/search.service';
import { ExpressionService } from '@core/services/expression/ExpressionService';
import { UserAuthService } from '@core/services/user-auth.service';
import { MenuService } from '@core';
import { Observable, of, Subject, Subscription } from 'rxjs/index';
import { map, mergeMap } from 'rxjs/operators';
import { SubjectService } from '@core/services/events/subject.service';
import { Events } from '@core/services/events/Events';
import { ReuseTabService } from '@shared/apes/reuse-tab';
import * as CryptoJS from 'crypto-js';
import { ApesModalRef, ApesModalService } from '@shared/apes/modal';
import { OaService } from '@core/services/oa.service';
import { ApesMessageService } from '@shared/apes/message';
import { ApesSearchFormComponent } from './apes-search-form/apes-search-form.component';
import { Platform } from '@angular/cdk/platform';
import {
  BreakpointObserver,
  BreakpointState,
  MediaMatcher,
  Breakpoints,
} from '@angular/cdk/layout';
import { FormService } from '@core/services/form.service';
import { StepsGuideService } from '@shared/apes/steps-guide';
import { DOCUMENT } from '@angular/common';
import { ButtonService } from '@core/services/button.service';
import { BatchPrintService } from '../query/batch-print/batch-print.service';
import { WebsocketService } from '@core/services/websocket/websocket.service';

@Component({
  selector: 'apes-form',
  templateUrl: './apes-form.component.html',
  // styleUrls: ['apes-form.component.scss'],
})
export class ApesFormComponent implements OnInit, OnDestroy {

  @ViewChild(ApesSearchFormComponent, { static: false })
  private apesSearchFormComponent: ApesSearchFormComponent;
  form: FormGroup;
  model: any = {};
  options: FormlyFormOptions = {};

  exhibitionData: any[] = [];

  /**容器高度**/
  _height: number = 0;

  direction = 'horizontal';
  // direction = 'vertical';
  leftSize = 30;
  /**关联跳转**/
  relevancyMetadata;
  /**表单区域元数据**/
  formMetadata = [];
  initFormMetadata = []; // 初始化数据
  /**按钮列表元数据**/
  btnBarMetadata = [];
  /**按钮列表**/
  btnBar = [];
  btnGroup = [];
  customBtn = [];
  hideBtnBar: boolean = false;
  /**状态列表**/
  statusBar = [];

  /**查找区域**/
  searchFormId: any;
  searchFormViewType = '';
  searchForm: FormGroup;
  searchModel: any = {};
  searchOption: FormlyFormOptions = {};
  searchFormMetadata: any;
  searchLoding = true;
  /**上下文环境变量**/
  ctx: any = {};

  /**用户信息**/
  user: any;

  /**订阅主题**/
  subjects = {};
  private change$: Subscription;
  tableValid = {};

  /**流程标记**/
  wfFlag: boolean = false;

  /**日志记录**/
  notes = [];

  /**流程实例编号**/
  processInstanceId: string = '';

  /**数据刷新Api**/
  findOneApi: string;

  /**幂等性控制**/
  oldModel: string;

  previousAction: string;

  // 更小屏幕
  XSmall = Breakpoints.XSmall;
  // 小屏幕
  Small = Breakpoints.Small;

  /**表单查找回调函数**/
  formSearchCallback: string;

  /** 操作指南 **/
  stepsGuide: boolean = false;

  /** 路由参数 **/
  urlModel: any = {};

  /** 第一次form初始化 **/
  firstFormInit: boolean = true;

  messagesSubscription: Subscription;

  constructor(protected route: ActivatedRoute,
              private modalService: ApesModalService,
              protected cd: ChangeDetectorRef,
              protected apiService: ApiService,
              protected reuseTabService: ReuseTabService,
              protected menuService: MenuService,
              protected searchService: SearchService,
              protected oaService: OaService,
              protected subject: SubjectService,
              protected expressionService: ExpressionService,
              protected userService: UserAuthService,
              protected msg: ApesMessageService,
              protected events: Events,
              private renderer: Renderer2,
              private platform: Platform,
              private formService: FormService,
              private buttonService: ButtonService,
              public bm: BreakpointObserver,
              public media: MediaMatcher,
              private stepService: StepsGuideService,
              private batchPrintService: BatchPrintService,
              @Inject(DOCUMENT) private doc: any,
              private ws: WebsocketService,
  ) {
    this.wsSubscribe();
  }

  private wsSubscribe() {
    this.messagesSubscription = this.ws.messagesObserver.subscribe(message => {
      const data = JSON.parse(message);
      /**待办消息通知**/
      if (data.topic === 'ws.todo') {
        const businessType = this.model['innerBusinessType'];
        const businessKey = this.model['innerBusinessKey'];
        if (missing(businessType) || missing(businessKey)) return;
        if (businessType === data.message.businessType && businessKey === data.message.businessKey) {
          this.refreshLogger(businessType, businessKey);
        }
      }
    });
  }

  ngOnInit() {
    // header:48,tabs:52,button:35,contentTop:8,contentBottom:8;
    if (this.platform.ANDROID) {
      this._height = window.innerHeight - 230;
      const position = document.querySelector('.apes-header');
      const display = document.querySelector('.statusBar');
      // this.renderer.setStyle(position, 'position', 'static');
      // this.renderer.setStyle(display, 'display', 'none');
    } else {
      this._height = document.querySelector('.content').clientHeight;
    }
    // this._height = document.querySelector('.content').clientHeight;
    this.form = new FormGroup({});
    this.searchForm = new FormGroup({ quickSearchInput: new FormControl('') });

    this.ctx.subjects = this.subjects;
    // this.initContext();
    // console.log(this.modal['apesComponentParams']['formId']);
    // let formId;
    // if(this.modal){
    //   formId =  this.modal['apesComponentParams']['formId']
    // }else{
    //   formId = this.route.snapshot.paramMap.get('formId');
    // }
    // let formId = this.route.snapshot.paramMap.get('formId');
    let formId = this.filterFormId();
    // console.log('test1');
    this.getFormMetadata(formId);

    /**拉模型：组件创建时初始化**/
    this.userService.getUser().subscribe(user => {
      this.user = user;
      this.ctx.user = this.user;
    });

    /**推模型：数据变更时主动触发**/
    this.userService.userSubject.subscribe(user => {
      this.user = user;
      this.ctx.user = this.user;
    });

    /**表单数据加载事件**/
    this.subject.subscribe(this.ctx, this.subject.event_form_load, data => {
      // 加载数据不一定为新增状态，增加一个参数， 默认为新增
      let resetStates = false;
      if (data.hasOwnProperty('resetStates')) {
        resetStates = data.resetStates;
      }
      this.refresh(data, resetStates);
      this.wfFlag = false;
      this.setBtnVisible();
      this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: '' });
    });

    /** 表单初始化事件 **/
    this.subject.subscribe(this.ctx, this.subject.event_form_init, data => {
      this.initContext();
      this.setBtnVisible();
      // this.subject.publish(this.ctx, this.subject.event_form_button, {ctx: this.ctx, action: 'action_new'});
      this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: '' });
    });

    /** 按钮不可用事件 **/
    this.subject.subscribe(this.ctx, this.subject.event_form_button_disable, data => {
      this.ctx.loading = data;
    });

    /** 页面按钮功能事件 **/
    this.subject.subscribe(this.ctx, this.subject.event_button, data => {
      this.buttonService.clickButton(data);
    });

    this.events.subscribe(this.getUrl(), data => {
      if (data.hasOwnProperty('newTask')) {
        this.refresh(data);
        delete this.formService.formData['key'];
        this.editStatus(data.btnMetadata);
      } else {
        this.executeTask(data);
      }
    });

    // let data = this.getRouteParam();
    // if (exists(data)) this.executeTask(data);

    /**流程执行后的刷新事件**/
    this.subject.subscribe(this.ctx, this.subject.event_wf_refresh, data => {
      this.apiService.post(data.findOneApi, { id: data.businessKey }).subscribe(body => {
        /**回填数据**/
        if (body) {
          this.refresh(body);
          this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: '' });
        }
      });
    });
    this.ctx['searchModel'] = this.searchModel;
    this.searchOption['formState'] = this.ctx;
    this.initContext();
  }

  oaMetadata = [
    {
      id: 'action_wf_submit', api: 'wf.executeTask',
      callbackfn: (btnMetadata, taskMetadata) => {
        btnMetadata.exclusiveGateway = [];
        delete btnMetadata['carbonCopy'];
        btnMetadata.label = taskMetadata.taskName;
        btnMetadata.extFields = taskMetadata.fields;
        if (taskMetadata.carbonCopy) btnMetadata.carbonCopy = taskMetadata.carbonCopy;
        if (!missingOrEmpty(taskMetadata.exclusiveGateway)) {
          let exclusiveGateway = taskMetadata.exclusiveGateway[0];
          if (!this.model.hasOwnProperty(exclusiveGateway.valueId)) { // !(exclusiveGateway.valueId in this.model)
            btnMetadata.exclusiveGateway = taskMetadata.exclusiveGateway;
          }
        }
      },
    }, // 待办执行
    { id: 'action_wf_resolve', api: 'wf.changeSign' }, // 转签
    { id: 'action_wf_apostille', api: 'wf.addSign' }, // 加签
    { id: 'action_wf_countersign', api: 'wf.counterSign' }, // 会签
  ];


  setContentHeight() {
    if (this.searchFormViewType === 'form') {
      setTimeout(() => {
        let apesRelevancyLink = document.querySelector('.apes-relevancy-link') ? document.querySelector('.apes-relevancy-link').clientHeight : 0;
        let height = document.querySelector('.content').clientHeight;
        this._height = height - apesRelevancyLink;
        // console.log('test2');
      }, 1000);
    }
  }

  /**
   * 功能：待办任务执行
   * @param taskMetadata
   */
  private executeTask(taskMetadata) {
    let findOneApi = taskMetadata.api || this.findOneApi;
    let routerTask = taskMetadata.routerTask;
    if (routerTask) {
      this.refresh(taskMetadata.body);
      delete this.formService.formData['key'];
      this.setStates('submit');
      this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: '' });
    } else {
      if (missing(findOneApi)) return;
      //非OA待办
      if (taskMetadata['OAInterface'] == false) {
        let postData;
        if (taskMetadata['carboncopy']) {
          postData = { id: taskMetadata.businessKey };
        } else {
          postData = { ...taskMetadata };
        }

        if (this.searchFormViewType === 'form') {
          delete this.formService.formData['key'];
          this.searchModel = { ...this.searchModel, ...postData };
          this.ctx['searchModel'] = this.searchModel;
          this.searchLoding = true;
          setTimeout(() => {
            this.apesSearchFormComponent._search(this.searchLoding);
          }, 500);
        } else {
          this.apiService.post(findOneApi, postData).subscribe(body => {
            delete this.formService.formData['key'];
            /**回填数据**/
            delete this.formService.formData['key'];
            if (body) {

              /**设置成编辑状态**/
              this.refresh(body);
              // this.setStates('submit');
              this.wfFlag = false;
              this.setBtnVisible();
              this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: '' });
            }
          });
        }

      } else {
        this.apiService.post(findOneApi, { id: taskMetadata.businessKey }).subscribe(body => {
          delete this.formService.formData['key'];
          /**回填数据**/
          delete this.formService.formData['key'];
          if (body) {

            this.wfFlag = taskMetadata.wfFlag === true ? true : false;
            this.refresh(body);

            /**设置成编辑状态**/
            if (taskMetadata.editable) this.setStates('submit');
            this.setBtnVisible(taskMetadata.auth);

            this.btnBar.forEach(btnMetadata => {
              this.oaMetadata.filter(m => m.id === btnMetadata.id).forEach(m => {
                btnMetadata.api = m.api;
                if (m.callbackfn) m.callbackfn(btnMetadata, taskMetadata);
                btnMetadata.businessKey = taskMetadata.businessKey;
                btnMetadata.findOneApi = findOneApi;
              });
            });
            this.model.wfTaskId = taskMetadata.taskId;
            // 用于判断是否需要提前转签，用于全局oa控制
            this.model.changeSignFlag = taskMetadata.changeSignFlag ? taskMetadata.changeSignFlag : false;
            this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: '' });
          }
        });
      }

    }

  }

  filterFormId() {
    let url = this.route.snapshot.paramMap.get('formId');
    let formId;
    let index = url.indexOf('_');
    if (index == -1) {
      formId = url;
    } else {
      formId = url.slice(0, index);
      let resData = url.slice(index + 1);
      let data = resData.split('&');
      let list = {};
      for (let key in data) {
        let obj = data[key];
        let dataIndex = obj.indexOf(':');
        let dataKey = obj.substring(0, dataIndex);
        let dataValue = obj.substring(dataIndex + 1);
        list[dataKey] = dataValue;
      }
      this.urlModel = list;
      this.ctx.urlModel = this.urlModel;
    }
    return formId;
  }

  private getRouteParam(): any {
    let params = this.route.snapshot.queryParams;
    if (exists(params.value)) {
      let value = params.value;
      value = CryptoJS.enc.Base64.parse(value);
      value = value.toString(CryptoJS.enc.Utf8);
      return JSON.parse(value);
    }
  }

  private getUrl(): string {
    let url = 'form/' + this.route.snapshot.paramMap.get('formId');
    return url;
  }

  ngOnDestroy(): void {
    let url = this.getUrl();
    this.events.unsubscribe(url, null);

    if (this.messagesSubscription) {
      this.messagesSubscription.unsubscribe();
    }
  }

  /**
   * 功能：初始化上下文环境变量
   */
  private initContext() {
    let oldModel = deepClone(this.model);
    this.clearValue(this.model);
    this.form.reset({});
    this.clearValue(this.searchModel);
    this.searchForm.reset({});
    this.clearValue(this.ctx);
    this.ctx.user = this.user;
    this.ctx.model = this.model;
    this.ctx.urlModel = this.urlModel;
    this.setStates('new');
    this.ctx.form = this.form;
    this.ctx.subjects = this.subjects;
    this.clearValue(this.tableValid);
    this.ctx.valid = true;
    this.ctx.loading = false;
    this.options.formState = this.ctx;
    this.ctx.searchService = this.searchService;
    this.ctx.screenSmall = false;
    this.ctx.screenSmall = this.bm.isMatched(this.XSmall) || this.bm.isMatched(this.Small);
    this.ctx.platform = this.userService.getUserInfoObj() ? this.userService.getUserInfoObj().platform : ''; // 判断平台
    this.ctx.formId = this.filterFormId(); // 记录页面地址
    // 动态表单配置
    if (this.formMetadata && this.formMetadata.length > 0) {
      this.ctx.$formMetadata = this.formMetadata;
      this.ctx.$initFormMetadata = this.initFormMetadata;
    }
    this.ctx.oldModel = oldModel;
    /**表格数据刷新**/
    this.subject.publish(this.ctx, this.subject.event_form_refresh, {});

    this.wfFlag = false;
    /**日志记录**/
    this.notes = [];
    /**流程实例编号**/
    this.processInstanceId = '';
    /**组件初始化数据**/
    this.subject.publish(this.ctx, 'initData', true);

    /**用于xml页面初始化订阅**/
    setTimeout(() => {
      if (!this.firstFormInit) {
        this.subject.publish(this.ctx, 'formInit', true);
      }
    }, 500);
  }

  /**
   * 功能：获取表单元数据
   */
  private getFormMetadata(formId) {
    this.getFormMetadataApi(formId).pipe(
      map((body) => {
        return body;
      }),
      mergeMap(data => this.getSearchFormMetadata(data)),
    ).subscribe((body) => {
      if (body.hasOwnProperty('stepsGuide')) {
        this.stepsGuide = true;
        setTimeout(() => {
          this.initStepsGuide(body.stepsGuide);
        }, 2000);
      }
      if (body.hasOwnProperty('exhibitionData')) {
        this.exhibitionData = JSON.parse(body.exhibitionData.replace(/^"|"$/g, '').replace(/'/g, '"'));
      }
      this.searchFormViewType = body.searchFormViewType || 'dialog';
      this.searchFormId = body.searchFormId;
      this.searchFormMetadata = body.searchFormMetadata;
      this.direction = body.direction || 'horizontal';
      // this.direction = body.direction || 'vertical';
      this.leftSize = body.leftSize || 30;
      if (this.searchFormViewType === 'list') this.leftSize = 100;
      let metadata = body.sheet;
      this.formService.extFormMetadata(this.searchFormMetadata, this.searchOption, this.subject, this.tableValid);
      this.formService.extFormMetadata(metadata, this.ctx, this.subject, this.tableValid);
      this.formMetadata = this.formMetadata.concat(metadata);

      this.ctx.$formMetadata = this.formMetadata;

      // 用于初始化表达结构
      let formMetadata = JSON.stringify(this.formMetadata);
      this.initFormMetadata = JSON.parse(formMetadata);
      if (body.hasOwnProperty('relevancy')) {
        this.relevancyMetadata = body.relevancy;
      }

      this.change$ = <any>this.menuService.change.subscribe(res => {

        // if (body.header.buttonbar != null) {
        //   this.auth(body.header.buttonbar);
        //   this.setBtnVisible();
        // }

        this.auth(body);

        this.cd.detectChanges();
      });
      if (body.header.statusbar != null) {
        this.statusBar = body.header.statusbar;
      }

      if (body.global) {
        this.interceptEventListener(body.global.events);
        if (body.global.api) this.findOneApi = body.global.api;
      }

      if (this.formService.formData.hasOwnProperty('key')) {
        let body = this.formService.formData['key'];
        if (body.hasOwnProperty('newTask')) {
          this.refresh(body);
          delete this.formService.formData['key'];
          this.editStatus(body.btnMetadata);
        } else {
          this.executeTask(body);
        }
      }
      if (body.hasOwnProperty('hideBtnBar')) {
        this.hideBtnBar = true;
      }
      this.events.publish('setContentHeight', true);
      this.setContentHeight();
      setTimeout(() => {
        this.subject.publish(this.ctx, 'formInit', true);
        this.firstFormInit = false;
      }, 500);
    });
  }

  /**
   * 功能：注册事件监听器
   * @param {string} topic
   */
  interceptEventListener(events: any[]) {
    if (missing(events)) return;
    events.forEach(em => {
      em.type.split(',').forEach(type => {
        if (type === this.subject.callback_form_search) {
          this.formSearchCallback = em.callback;
        } else {
          /**订阅事件**/
          this.subject.subscribe(this.ctx, type, data => {
            this.expressionService.evaluate(em.callback, {
              context: this.ctx,
              form: this.form,
              model: this.model,
              data: data,
            }, true);
          });
        }
      });
    });
  }

  private getFormMetadataApi(formId: string): Observable<any> {
    return this.apiService.post('form.get', { 'body': getJson({ id: formId }) }).pipe(map(
      (body) => {
        if (body) {
          // console.log(body);
          return body;
        }
      }));
  }

  private getSearchFormMetadata(data): Observable<any> {
    if (data.searchFormViewType === 'form' || data.searchFormViewType == 'list') {
      if (data.searchFormViewType === 'list') this.leftSize = 100;
      return this.apiService.post('form.search.get', { 'body': JSON.stringify({ 'id': data.searchFormId }) }).pipe(map(
        (body) => {
          if (body) {
            return { searchFormMetadata: body, ...data };
          }
        }));
    } else {
      return of(data);
    }
  }

  /**
   * 功能：权限过滤
   * @param {any[]} body 所有的操作
   * @returns {any[]}
   */
  private auth(body: any): void {

    let btnMetadata;
    let intersection;
    /** 权限操作 **/
    let operations = this.getOperations();

    if (body.header.buttonbar != null) {
      btnMetadata = body.header.buttonbar;
      intersection = btnMetadata.filter(metadata => {
        if (metadata.id === 'action_submit' || metadata.id === 'action_cancel' || metadata.wf === 'true') {
          return true;
        }
        for (let o of operations) {
          if (o.operationId === metadata.id) {
            metadata.api = o.api;
            metadata.report = o.report;
            return true;
          }
        }
      });
    } else {
      intersection = [];
    }

    operations.forEach((o) => {
      if (o.operationId.indexOf('custom_') != -1) {
        let data = {
          ...o,
          id: o.operationId,
          wf: 'false',
          customBtn: true,
        };
        intersection.push(data);
      }
    });

    this.btnBarMetadata = intersection;

    this.setBtnVisible();
  }

  /**
   * 功能：获取当前页面可操作按钮信息
   * @returns {any[]}
   */
  private getOperations(): any[] {
    let menu = this.getMenu();
    if (menu && menu.operations) {
      return menu.operations;
    }
    return [];
  }

  /**
   * 功能：获取当前页面菜单信息
   * @returns {any}
   */
  private getMenu() {
    let curURL = this.reuseTabService.getUrl(this.route.snapshot);
    const menus = this.menuService ? this.menuService.getPathByUrl(curURL.replace('/fn/', '/')) : [];
    if (!menus || menus.length === 0) return null;
    return menus.pop();
  }

  onMouseOver(btnMetaData: any) {
    if (this.ctx.hasOwnProperty('gridCellEditorStopped') && !this.ctx.gridCellEditorStopped) {
      this.subject.publish(this.ctx, this.subject.event_grid_cell_stop_editor, {});
    }

  }

  /**
   * 功能：按钮事件路由
   * @param btnMetadata 当前按钮元数据
   */
  onEvent(btnMetadata: any) {
    if (this.ctx.hasOwnProperty('gridCellEditorStopped') && !this.ctx.gridCellEditorStopped) {
      this.msg.error('表格数据有未提交提交');
      return;
    }
    if (btnMetadata instanceof MouseEvent) return;
    if (this.ctx.loading) {
      this.msg.warning('有数据在提交中,请不要反复点击按钮！', { apesDuration: 3000 });
      return;
    }

    if (!missing(this.model['id']) && !missing(this.ctx['id']) && this.model['id'] != this.ctx['id']) {
      console.warn('单号与内容不一致，不允许提交！');
      return;
    }

    if (btnMetadata) {
      if (this.btnBar.length == 0 || this.btnBar.filter(m => m.id === btnMetadata.id).length == 0) {
        if (this.btnGroup.length == 0) {
          this.msg.warning('权限不足，请重新提交！', { apesDuration: 3000 });
          return;
        }
      }

      if (btnMetadata.id === 'action_new') {
        this.action_new(btnMetadata);
        this.btnInit(btnMetadata);
        if (this.searchFormViewType === 'list') this.leftSize = 0;
      } else if (btnMetadata.id === 'action_cancel') {
        this.showConfirm('是否放弃当前在编辑的数据', btnMetadata);
      } else if (btnMetadata.id === 'action_search') {
        this.action_search(btnMetadata);
        this.btnInit(btnMetadata);
      } else if (btnMetadata.id === 'action_print' || btnMetadata.id.startsWith('action_print')) {
        this.action_print(btnMetadata);
      } else if (btnMetadata.wf === 'true') {
        this.action_oa(btnMetadata);
      } else if (btnMetadata.id === 'action_download') {
        this.action_download(btnMetadata);
      } else {
        if (btnMetadata.hasOwnProperty('callback')) {
          this.callbackConfirm(btnMetadata);
        } else if (btnMetadata.hasOwnProperty('confirmApi')) {
          this.showConfirmApi(btnMetadata);
        } else if (btnMetadata.confirm === 'true') {
          this.showConfirm('是否执行 [' + btnMetadata.label + '] 操作？', btnMetadata);
        } else {
          this.submit(btnMetadata);
        }
      }
    }
  }

  /**
   * 定制提示
   * @param msg 提示内容
   * @param data 按钮配置参数
   * @param step 步骤
   */
  showConfirm(msg, data: any, step: any = '') {
    if (step != '' && (data.confirmBtn || data.secondaryConfirmBtn)) {
      let footer: any[];
      if (step == 'first') {
        footer = getO(data.confirmBtn);
      } else if (step == 'secondary') {
        footer = getO(data.secondaryConfirmBtn);
      }
      // let that = this;
      footer.map((btn) => {
        if (btn.value == 'cancel') {
          btn.onClick = () => {
            this.modalService.closeAll();
            if (this.searchFormViewType === 'list') this.leftSize = 100;
          };
        } else {
          btn.onClick = () => {
            this.model[btn.key] = btn.value;
            this.submit(data);
            this.modalService.closeAll();
          };
        }
      });
      this.modalService.create({
        apesTitle: msg.title ? msg.title : null,
        apesContent: msg.content ? msg.content : msg,
        apesFooter: footer,
      });
    } else {
      let okText = data['okText'] ? data['okText'] : '确认';
      let cancelText = data['cancelText'] ? data['cancelText'] : '取消';

      this.modalService.confirm({
        apesTitle: msg.title ? msg.title : msg,
        apesContent: msg.content ? msg.content : null,
        apesOkText: okText,
        apesOkType: 'primary',
        apesOnOk: () => {
          if (this.searchFormViewType === 'list') this.leftSize = 100;
          if (data.id === 'action_cancel') {
            this.action_cancel(data);
            // 用于二次提示
          } else if (data.hasOwnProperty('promptConfirm')) {
            this.model['promptConfirm'] = true;
            this.submit(data);
          } else {
            this.submit(data);
          }
        },
        apesCancelText: cancelText,
        apesOnCancel: () => {
          // 用于二次提示
          if (this.searchFormViewType === 'list') this.leftSize = 0;
          if (data.hasOwnProperty('promptConfirm')) {
            this.model['promptConfirm'] = false;
            this.submit(data);
          }
          // console.log('Cancel');
        },
      });
    }

  }

  /**
   * 用于调用后端定制提示
   * @param data
   */
  showConfirmApi(data: any): void {
    if (data['firstConfirm']) {
      this.apiService.post(data.confirmApi, this.model).subscribe(msg => {
        let res = JSON.stringify(msg);
        if (res == '' || res == '{}') {
          let title = '是否执行 [' + data.label + '] 操作？';
          this.showConfirm(title, data);
        } else if (msg == 'noShowConfirm') {
          this.submit(data);
        } else {
          if (data['secondaryApi']) {
            this.showConfirmSecondaryApi(msg, data);
          } else {
            this.showConfirm(msg, data, 'first');
          }
        }
      });
    } else {
      let title = '是否执行 [' + data.label + '] 操作？';
      this.modalService.confirm({
        apesTitle: title,
        apesOkText: '确认',
        apesOkType: 'primary',
        apesOnOk: () => {
          this.apiService.post(data.confirmApi, this.model)
            .subscribe(msg => {
              if (msg != '') {
                this.showConfirm(msg, data, 'first');
              } else if (msg === '') {
                this.submit(data);
              }
            });
        },
        apesCancelText: '取消',
        apesOnCancel: () => console.log('Cancel'),
      });
    }
  }

  /**
   * 用于多次定制提示
   * @param msg
   * @param data
   */
  showConfirmSecondaryApi(msg, data: any): void {
    if (data.confirmBtn) {
      let footer: any[] = getO(data.confirmBtn);
      footer.map((btn) => {
        if (btn.value == 'cancel') {
          btn.onClick = () => {
            this.modalService.closeAll();
          };
        } else {
          if (btn.api) {
            btn.onClick = () => {
              this.model[btn.key] = btn.value;
              this.modalService.closeAll();
              this.apiService.post(btn.api, this.model).subscribe(msg => {
                let res = JSON.stringify(msg);
                if (res == '' || res == '{}') {
                  this.submit(data);
                } else {
                  this.showConfirm(msg, data, 'secondary');
                }
              });
            };
          } else {
            btn.onClick = () => {
              this.model[btn.key] = btn.value;
              this.submit(data);
              this.modalService.closeAll();
            };
          }
        }
      });
      this.modalService.create({
        apesTitle: msg.title ? msg.title : null,
        apesContent: msg.content ? msg.content : msg,
        apesFooter: footer,
      });
    } else {
      this.modalService.confirm({
        apesTitle: msg,
        apesOkText: '确认',
        apesOkType: 'primary',
        apesOnOk: () => {
          this.apiService.post(data.secondaryApi, this.model)
            .subscribe(msg => {
              let res = JSON.stringify(msg);
              if (res == '' || res == '{}') {
                this.submit(data);
              } else {
                this.showConfirm(msg, data, 'secondary');
              }
            });
        },
        apesCancelText: '取消',
        apesOnCancel: () => console.log('Cancel'),
      });
    }
  }

  /**
   * 用于配置xml二次提示
   * @param data
   */
  callbackConfirm(data: any): void {
    let msg = this.expressionService.evaluate(data.callback, {
      context: this.ctx,
      form: this.form,
      model: this.model,
    });
    // 用于二次提示
    if (data.hasOwnProperty('promptConfirm')) {
      let title = '是否执行 [' + data.label + '] 操作？';
      this.modalService.confirm({
        apesTitle: title,
        apesOkText: '确认',
        apesOkType: 'primary',
        apesOnOk: () => {
          if (msg) {
            this.showConfirm(msg, data, 'secondary');
          } else {
            this.submit(data);
          }
        },
        apesCancelText: '取消',
        apesOnCancel: () => console.log('Cancel'),
      });
    } else if (msg) {
      this.showConfirm(msg, data);
    } else {
      this.submit(data);
    }
  }

  /**
   * 功能：新增事件
   * @param btnMetadata
   */
  private action_new(btnMetadata: any) {
    this.initContext();
    // this.btnInit(btnMetadata);
    this.setBtnVisible();
    this.submit(btnMetadata);
    this.previousAction = btnMetadata.id;
  }

  /**
   * 功能：取消事件
   * @param btnMetadata
   */
  private action_cancel(btnMetadata: any) {
    let businessKey = this.model.innerBusinessKey;
    this.wfFlag = false;
    this.initContext();
    if (this.previousAction != 'action_new' && exists(this.findOneApi) && (exists(businessKey) || !missingOrEmptyObject(this.ctx.oldModel))) {
      this.apiService.post(this.findOneApi, exists(businessKey) ? { id: businessKey } : this.ctx.oldModel).subscribe(body => {
        /**回填数据**/
        if (body) this.refresh(body);
      });
    }
    this.setBtnVisible();
    this.btnInit(btnMetadata);
    this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: btnMetadata.id });
    this.notes = [];
    this.processInstanceId = '';
    this.previousAction = btnMetadata.id;
  }

  /**
   * 功能：查找事件
   * view_type:dialog,
   * @param btnMetadata
   */
  private action_search(btnMetadata: any) {
    if (this.searchFormViewType === 'dialog') {
      /**调用查找，并回填数据**/
      this.setButtonLoadingStatus('action_search', true);
      this.searchService.openDialog(btnMetadata.api, false, (result: any) => {
        if (result && result.length > 0) {
          let data = result[0];
          let callBackSubject = new Subject();

          /**回填数据**/
          callBackSubject.subscribe(data => {
            this.wfFlag = false;
            this.refresh(data);
            this.setButtonLoadingStatus('action_search', false);
            this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: btnMetadata.id });
          });

          if (this.formSearchCallback) {
            this.expressionService.evaluate(this.formSearchCallback, {
              context: this.ctx,
              form: this.form,
              model: this.model,
              data: data,
            }).subscribe(body => {
              if (body) {
                callBackSubject.next(body);
              } else {
                this.msg.error('未查询到相应的单据！');
              }
            });
          } else {
            callBackSubject.next(data);
          }
        } else if (result && result instanceof Object) {
          this.wfFlag = false;
          this.refresh(result);
          this.setButtonLoadingStatus('action_search', false);
          this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: btnMetadata.id });
        } else {
          this.setButtonLoadingStatus('action_search', false);
        }
      }).subscribe();
    } else {
      this.searchLoding = true;
      this.apesSearchFormComponent._search(this.searchLoding);
    }
    this.previousAction = btnMetadata.id;
  }

  /**
   * 功能： 下载事件
   */
  private action_download(btnMetadata) {
    console.log(btnMetadata);
    if (this.searchFormViewType !== 'dialog') {
      this.setButtonLoadingStatus('action_download', true);
      this.apesSearchFormComponent._download(btnMetadata.api, () => {
        this.setButtonLoadingStatus('action_download', false);
      });
    }
  }

  /**
   * 解决界面输入单号后没有内容没有变更，造成内容与单号不一致问题
   **/
  private checkIdchanged(): boolean {
    if (missing(this.model['id']) && !missing(this.ctx['id'])) {
      this.msg.warning('单号为空，不允许提交！', { apesDuration: 2000 });
      return true;
    }
    if (!missing(this.model['id']) && !missing(this.ctx['id']) && this.model['id'] != this.ctx['id']) {
      this.msg.warning('单号与内容不一致，不允许提交！', { apesDuration: 2000 });
      return true;
    }
    return false;
  }

  private action_oa(btnMetadata: any) {
    if (this.checkIdchanged()) return;

    if (!missingOrEmpty(btnMetadata.extFields)) {
      let context = {};
      btnMetadata.extFields.forEach(field => {
        if (exists(this.model[field.key])) {
          context[field.key] = this.model[field.key];
        }
      });
      btnMetadata.context = context;
    }

    this.oaService.openDialog(btnMetadata, (result: any) => {
      if (result) {
        /**回填数据**/
        for (let key in result) {
          this.model[key] = result[key];
        }
        if (missing(btnMetadata.api)) return;
        this.ctx.loading = true;
        this.apiService.post(btnMetadata.api, this.model)
          .subscribe(body => {
            /**回填数据**/
            this.ctx.loading = false;
            if (body) {
              this.wfFlag = false;
              this.subject.publish(this.ctx, this.subject.event_wf_refresh, {
                ctx: this.ctx,
                metadata: btnMetadata,
                action: btnMetadata.id,
                findOneApi: btnMetadata.findOneApi,
                businessKey: btnMetadata.businessKey,
              });
            }
          });
      }
    });
    this.previousAction = btnMetadata.id;
  }

  private action_print(btnMetadata: any) {
    // this.checkedPrint(btnMetadata);
    if (btnMetadata.hasOwnProperty('printConfirm')) {
      this.checkedPrint(btnMetadata);
    } else if (btnMetadata.hasOwnProperty('batchPrinting')) {
      this.batchPrinting(btnMetadata);
    } else {
      let msg = '';
      let setData = { id: this.model.id };
      this.apiService.post('print.record.findOne', setData).subscribe((body) => {
        if (body >= 0) {
          msg = '该单据第' + (body + 1) + '次打印';

          this.modalService.info({
            apesTitle: msg,
            apesOkText: '确认',
            apesOkType: 'primary',
            apesOnOk: () => {
              this.checkedPrint(btnMetadata);
            },
            apesCancelText: '取消',
            apesOnCancel: () => {
            },
          });
        }
      });
    }
  }


  batchPrinting(btnMetadata) {
    let options = {
      multiple: true,
      uniqueKey: 'id',
      addSame: false,
      valueFormatter: 'value.id',
      checkboxSelect: true,
      defaultCheckbox: true,
    };
    let formId = btnMetadata.report;
    let api = btnMetadata.printApi ? btnMetadata.printApi : this.findOneApi;
    this.searchService.openDialog(btnMetadata.api, options, (result: any) => {
      // console.log(result);
      if (result && result.length > 0) {
        this.batchPrintService.batchPrinting(formId, api, result);
      }
    }).subscribe();
  }


  private checkedPrint(btnMetadata: any) {
    if (exists(btnMetadata.report)) {
      this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: btnMetadata.id });

      this.apiService.post('report.getUrl', {}).subscribe((body) => {
        if (exists(body)) {
          console.log(body);
          let reportUrl = body;
          if (btnMetadata.hasOwnProperty('printType')) {
            // preview : '预览',pdf : 'PDF',excel : 'Excel'
            let printType = btnMetadata.printType;
            let token;
            switch (printType) {
              case 'preview' :
                token = 'preview?';
                break;
              case 'pdf' :
                token = 'pdf/show?';
                break;
              case 'excel' :
                token = 'excel?';
                break;
            }
            reportUrl = reportUrl.replace('pdf/show?', token);
          }
          console.log('reportUrl:', reportUrl);
          let reportName = btnMetadata.report;
          let id = this.model.id;
          this.recordPrint();
          window.open(reportUrl + reportName + '&id=' + id);
        }
      });
      this.previousAction = btnMetadata.id;
    }
  }

  private recordPrint() {
    this.apiService.post('print.record.setPrintRecordNumber', this.model).subscribe((body) => {
      // console.log('打印记录', body);
    });
  }

  /**
   * 功能：根据表达式设置按钮可视化
   */
  private setBtnVisible(oaAuth?: string) {
    this.btnBar = [];
    this.customBtn = [];
    this.btnGroup = [];
    for (let metadata of this.btnBarMetadata) {
      let hide = metadata.hide || 'false';
      if (this.wfFlag === true) {
        if (metadata.wf === 'true' || metadata.id === 'action_cancel' || metadata.id.indexOf('action_print') != -1) {
          if (exists(metadata.auth) && exists(oaAuth) && oaAuth.toUpperCase().indexOf(metadata.auth) == -1) continue;
          this.btnBar.push(metadata);
        }
      } else {
        if (metadata.hasOwnProperty('customBtn')) {
          this.customBtn.push(metadata);
        } else if (this.expressionService.eval(hide, {
          context: this.ctx,
          form: this.form,
          model: this.model,
        }) == false) {
          if (metadata.hasOwnProperty('btnGroup')) {
            let check = true;
            this.btnGroup.forEach((btn) => {
              if (btn.name == metadata.btnGroup) {
                btn.btnList.push(metadata);
                check = false;
              }
            });
            if (check) {
              let bar = {
                name: metadata.btnGroup,
                btnList: [...metadata],
              };
              this.btnGroup.push(bar);
            }
          } else if (metadata.wf === 'false') {
            this.btnBar.push(metadata);
          }
        }
      }
    }
    this.cd.detectChanges();
    this.ctx['customBtn'] = this.customBtn;
  }

  /**
   * 功能：增加按钮加载中动画
   * @param {string} operationId 按钮Id
   * @param {boolean} status 设置状态
   */
  setButtonLoadingStatus(operationId: string, status: boolean) {
    const tempButtonBar = this.btnBar.map((button) => {
      if (button.id === operationId) {
        button['loading'] = status;
        button['disabled'] = status;
      }
      return button;
    });

    this.btnBar = [];
    this.btnBar = tempButtonBar;
    this.ctx['customBtn'] = this.btnBar;
  }

  /**
   * 功能：按钮上下文环境变量处理
   * @param btnMetadata
   */
  private btnInit(btnMetadata: any) {
    /**上下文环境变量处理**/
    let context = btnMetadata.context;
    if (context) {
      context = getO(context);
      this.fillField(context, []);
    }
  }

  private fillField(context: any, keys: string[]) {
    for (let key in context) {
      let value = context[key];
      let t = type(value);
      if (t === 'object' && key === 'model') {
        keys.push(key);
        this.fillField(value, keys);
      } else {
        if (t === 'string') {
          let text = getText(value);
          if (text) {
            value = getValueUsingField(this.ctx, text, true);
          }
        }
        if (keys.length > 0) {
          setTimeout(() => {
            // let currentObject: any;
            // currentObject = this.getCurrentObject(this.ctx, keys);
            // currentObject[key] = value;
            const m = {};
            m[key] = value;
            this.form.patchValue(m);
            this.model[key] = value;
          });
        } else {
          this.ctx[key] = value;
        }

      }
    }
  }


  private getCurrentObject(data: any, keys: string[]): any {
    let currentObject = data;
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < keys.length; i++) {
      currentObject = currentObject[keys[i]];
      if (missing(currentObject)) {
        return null;
      }
    }
    return currentObject;
  }

  editStatus(btnMetadata) {
    /**设置成编辑状态**/
    this.setStates('submit');
    this.setBtnVisible();
    this.btnBar.filter(m => m.id === 'action_submit')
      .forEach(m => {
        m.api = btnMetadata.api;
      });
    this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: btnMetadata.id });
    this.previousAction = btnMetadata.id;
  }

  /**
   * 功能：按钮提交事件
   * @param btnMetadata
   */
  private submit(btnMetadata: any) {
    let step = btnMetadata.step || 'one';
    if (step === 'two') {
      if (this.searchFormViewType === 'list') this.leftSize = 0;
      this.editStatus(btnMetadata);
      return;
    }
    if (missing(btnMetadata.api)) {
      this.subject.publish(this.ctx, this.subject.event_form_button, {
        ctx: this.ctx,
        action: btnMetadata.id,
        report: btnMetadata.report,
      });
      return;
    }
    // if (!this.checkFormChange()) {
    //   this.msg.warning('数据未变更，不允许提交！', {apesDuration: 5000});
    //   return;
    // }
    // for (const i in this.form.controls) {
    //   this.form.controls[i].markAsDirty();
    //   this.form.controls[i].updateValueAndValidity();
    //   this.form.controls[i].markAsTouched();
    // }
    this.checkFormValid(this.form.controls);

    if (!this.form.valid && btnMetadata.id == 'action_submit') {
      this.msg.warning('有必填项未录入，不允许提交！', { apesDuration: 2000 });
      return;
    }
    if (!this.ctx.valid && btnMetadata.id == 'action_submit') {
      this.msg.warning('明细有必填项未录入，不允许提交！', { apesDuration: 2000 });
      return;
    }

    if (this.checkIdchanged()) return;
    if (this.ctx.loading) return;

    btnMetadata.loading = true;
    this.ctx.loading = true;

    let filterModel = this.exhibitionData.length !== 0
      ? Object.keys(this.model).reduce((acc, key) => {
        if (!this.exhibitionData.includes(key)) {
          acc[key] = this.model[key];
        }
        return acc;
      }, {})
      : this.model;


    this.apiService.post(btnMetadata.api, filterModel)
      .subscribe(body => {
        btnMetadata.loading = false;
        this.ctx.loading = false;
        /**回填数据**/
        if (body) {
          let localModel = deepClone(this.model);
          this.wfFlag = false;
          this.refresh(body);
          this.subject.publish(this.ctx, this.subject.event_form_button, { ctx: this.ctx, action: btnMetadata.id });
          this.btnInit(btnMetadata);
          if (this.searchFormViewType === 'form') {
            if (btnMetadata.id === 'action_delete') {
              this.apesSearchFormComponent.refreshRowData(localModel, btnMetadata.id);
            } else {
              this.apesSearchFormComponent.refreshRowData(body, btnMetadata.id);
            }
          }
          this.previousAction = btnMetadata.id;
        }
      });
  }

  private setStates(states: string) {
    this.ctx.states = states;
  }

  /**
   * 功能：表单数据刷新
   * @param data
   */
  private refresh(data, resetStates = true) {
    if (resetStates) {
      this.setStates('new');
    }
    this.clearValue(this.model);
    for (let key in data) {
      this.model[key] = data[key];
      if (key == 'id') {
        this.ctx[key] = data[key];
      }
    }
    this.form.reset(data);
    this.oldModel = CryptoJS.MD5(JSON.stringify(this.model)).toString();
    this.subject.publish(this.ctx, this.subject.event_form_refresh, data);
    this.setBtnVisible();
    this.refreshLogger(data.innerBusinessType, data.innerBusinessKey);
  }

  private refreshLogger(businessType: string, businessKey: string) {
    this.notes = [];
    this.processInstanceId = '';
    if (exists(businessKey) && exists(businessType)) {
      let api = this.urlModel.loggerApi || 'ir.logger.find';
      this.apiService.post(api, {
        businessKey: businessKey,
        businessType: businessType,
      })
        .pipe(
          map((body) => {
            return body;
          }),
          mergeMap(item => this.getProcessInstanceExt(businessType, businessKey, item)),
          mergeMap(item => this.getStateMachineTodo(businessType, businessKey, item)),
        ).subscribe((body) => {
        this.notes = body.notes;
        this.processInstanceId = body.processInstanceId;
      });
    }
  }

  private getProcessInstanceExt(businessType: string, businessKey: string, item) {
    return this.apiService.post('wf.findProcessInstanceExt', {
      businessKey: businessKey,
      businessType: businessType,
    }).pipe(
      map((body) => {
        if (body) {
          return { processInstanceId: body.processInstanceId, notes: item };
        } else {
          return { notes: item };
        }
      }));
  }

  private getStateMachineTodo(businessType: string, businessKey: string, item) {
    return this.apiService.post('todo.findTodoTask', {
      businessKey: businessKey,
      businessType: businessType,
    }).pipe(
      map((body) => {
        if (body) {
          body['todoFlag'] = true;
          let notes = item['notes'];
          item['notes'] = [...body, ...notes];
        }
        return item;
      }));
  }

  private clearValue(object: any) {
    for (let key in object) {
      if (key.startsWith('grid_')) continue;
      delete object[key];
    }
  }

  checkFormChange(): boolean {
    const current = CryptoJS.MD5(JSON.stringify(this.model)).toString();
    return this.oldModel !== current ? true : false;
  }

  checkFormValid(controls) {
    for (const i in controls) {
      controls[i].markAsDirty();
      controls[i].markAsTouched();
      if (controls[i].hasOwnProperty('controls')) {
        this.checkFormValid(controls[i].controls);
      }
    }
  }

  steps: any = [];
  stepsItem: any = [
    // {
    //   pageName: 'steps-demo',
    //   target: 'test1',
    //   position: 'bottom-right',
    //   topFix: 6,
    //   steps: {
    //     title: 'Step 1',
    //     content: 'Guide Content',
    //   },
    // },
    // {
    //   pageName: 'steps-demo',
    //   target: 'test2',
    //   position: 'bottom-right',
    //   topFix: 6,
    //   steps: {
    //     title: 'Step 2',
    //     content: 'Guide Content',
    //   },
    // },
    // {
    //   pageName: 'steps-demo',
    //   target: 'test3',
    //   position: 'bottom-right',
    //   topFix: 6,
    //   leftFix: -48,
    //   steps: {
    //     title: 'Step 3',
    //     content: 'Guide Content',
    //   },
    // },
  ];

  initStepsGuide(steps) {
    steps = getO(steps);
    this.stepsItem = deepClone(steps);
    this.stepsItem.forEach((step) => {
      step['targetElement'] = this.getTargetId(step.target);
      this.steps.push(step.steps);
    });
  }

  getTargetId(id) {
    let target = this.doc.getElementById(id);
    return target;
  }

  resetStepsGuide(index = 0) {
    this.stepService.showGuide(false);
    localStorage.removeItem('devui_guide_steps-demo');
    this.stepService.setSteps(this.steps);
    this.stepService.setCurrentIndex(index);
  }

}
